package org.example.order;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.StateMachineBuilder;

import java.util.EnumSet;

@Configuration
public class OrderStateMachineBuilder {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(OrderStateMachineBuilder.class);

    public final static String MACHINEID = "orderStateMachine";

    public StateMachine<OrderStatus, OrderEvent> build(BeanFactory beanFactory) throws Exception {
        StateMachineBuilder.Builder<OrderStatus, OrderEvent> builder = StateMachineBuilder.builder();
        LOGGER.info("构建订单状态机");

        builder.configureConfiguration()
                .withConfiguration()
                .machineId(MACHINEID)
                .beanFactory(beanFactory);

        builder.configureStates()
                .withStates()
                .initial(OrderStatus.UNPAID)
                .states(EnumSet.allOf(OrderStatus.class));

        builder.configureTransitions()
                .withExternal()
                .source(OrderStatus.UNPAID).target(OrderStatus.WAITING_FOR_DELIVER)
                .event(OrderEvent.PAY)
                // 加了 action 和捕获异常的 action
                .action(action(),errorAction())
                .and()
                .withExternal()
                .source(OrderStatus.WAITING_FOR_DELIVER).target(OrderStatus.WAITING_FOR_RECEIVE)
                .event(OrderEvent.DELIVER)
                .action(action(),errorAction())
                .and()
                .withExternal()
                .source(OrderStatus.WAITING_FOR_RECEIVE).target(OrderStatus.DONE)
                .event(OrderEvent.RECEIVE)
                .action(action(),errorAction());

        return builder.build();
    }

    @Bean
    public Action<OrderStatus, OrderEvent> action() {
        return new Action<OrderStatus, OrderEvent>() {

            @Override
            public void execute(StateContext<OrderStatus, OrderEvent> context) {
                // do something
                LOGGER.info("source:{},target:{},action 行为： {}",context.getSource().getId(),context.getTarget().getId(),context.getMessage().getPayload());
                throw new RuntimeException(context.getMessage().getPayload()+" 抛出一个异常。。。。。。。。。");
                // 可以模拟抛出异常，将会触发 errorAction
                //throw new RuntimeException("xxx 异常");
            }
        };
    }

    @Bean
    public Action<OrderStatus, OrderEvent> errorAction() {
        return new Action<OrderStatus, OrderEvent>() {

            @Override
            public void execute(StateContext<OrderStatus, OrderEvent> context) {
                Exception exception = context.getException();
                // RuntimeException("MyError") added to context
                LOGGER.error("action 行为-捕获异常： {}",context.getMessage());
            }
        };
    }
}